/******************************************************************************

          Copyright (C), 2001-2015, Hisilicon Technologies Co., Ltd.
 ******************************************************************************
 File Name       : loader_cipher.c
 Version         : Initial draft
 Author          : Device Chipset STB Development Dept
 Created Date    : 2016-07-29
 Last Modified by: sdk
 Description     :
 Function List   :
 Change History  :
 Version  Date        Author     DefectNum         Description
 main\1   2016-07-29  sdk  N/A               Create this file.
 ******************************************************************************/

/******************************************************************************/
/*  Header file references                                                    */
/*  Quote order                                                               */
/*  1. Global header file                                                     */
/*  2. Public header files of other modules                                   */
/*  3. Header files within this module                                        */
/*  4. Private files within this module (.inc)                                */
/******************************************************************************/

#ifdef HI_LOADER_BOOTLOADER
#ifdef HI_MINIBOOT_SUPPORT
#include <stdio.h>
#include <string.h>
#else
#include "common.h"
#endif
#else
#include <stdio.h>
#include <string.h>
#endif

#include "hi_unf_cipher.h"
#include "dcas_debug.h"
#include "dcas_config.h"
#include "dcas_cipher.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */


#define SSA_LEN_HMAXVALUE           (32)
#define SSA_LEN_RSA_PUBLIC_KEY_E    (256)
#define SSA_LEN_RSA_PUBLIC_KEY_N    (256)
#define SSA_POS_RSA_PUBLIC_KEY_E    (508)

HI_U8 g_au8CustomerRSAPublicKey_N[SSA_LEN_RSA_PUBLIC_KEY_N] =
{
    0xa0, 0x49, 0xee, 0x54, 0x0d, 0x64, 0xec, 0x22, 0x33, 0x1d, 0x1b, 0x73, 0x2b, 0x14, 0x56, 0xfa,
    0xb8, 0xe4, 0x2d, 0x08, 0x64, 0xd4, 0x8b, 0xe8, 0xbc, 0x53, 0x8c, 0xba, 0x15, 0xc5, 0x67, 0xe8,
    0xc6, 0xaa, 0xa5, 0xa1, 0xbb, 0x25, 0xef, 0x4c, 0x43, 0x39, 0x4a, 0xf3, 0x33, 0xe8, 0xe6, 0x28,
    0xe9, 0x28, 0x82, 0x7b, 0x8f, 0x6b, 0x9c, 0xbc, 0x8b, 0xe4, 0x70, 0x44, 0xa6, 0xba, 0xf9, 0xbc,
    0x27, 0xb0, 0xfb, 0xee, 0x01, 0xf6, 0x4a, 0xb8, 0x97, 0x88, 0x9a, 0xc9, 0xdb, 0x4b, 0x18, 0xc6,
    0x24, 0xea, 0x6d, 0xec, 0x93, 0x37, 0xa0, 0x22, 0x00, 0xdc, 0x80, 0x70, 0xe7, 0x5a, 0x6e, 0x6a,
    0x96, 0x37, 0xe0, 0x81, 0xc8, 0xd8, 0x9b, 0x5f, 0xa7, 0x65, 0x7a, 0x34, 0xf6, 0x82, 0x87, 0xc9,
    0xd2, 0xa2, 0xaa, 0xa9, 0x7a, 0x2c, 0x69, 0x4a, 0xac, 0xf8, 0x3d, 0x7b, 0x7c, 0x20, 0x29, 0x12,
    0x43, 0xb2, 0x1b, 0x61, 0x7e, 0xe5, 0x7d, 0xb6, 0x77, 0xe6, 0x17, 0x23, 0x34, 0xc8, 0xed, 0xaf,
    0xd1, 0x83, 0xe3, 0xe1, 0x20, 0xb7, 0xaf, 0x51, 0x8f, 0xdc, 0xa2, 0x2b, 0x76, 0x7e, 0x80, 0x64,
    0x9a, 0x28, 0x26, 0x65, 0x19, 0x05, 0xdc, 0xd6, 0xdb, 0x1f, 0x6b, 0x2f, 0xc0, 0xfd, 0xc6, 0x79,
    0x2a, 0x37, 0xfb, 0xf4, 0x60, 0xd5, 0x9c, 0x4c, 0x16, 0x76, 0x64, 0xe4, 0x9b, 0xa5, 0x28, 0x50,
    0x71, 0x61, 0xdf, 0xa2, 0xc3, 0x8a, 0x21, 0x89, 0x3f, 0xde, 0x67, 0x8c, 0x09, 0x1c, 0xc1, 0x1f,
    0xdb, 0x57, 0x9f, 0x4a, 0x41, 0x4e, 0x09, 0x98, 0x94, 0x53, 0xe7, 0xc2, 0x86, 0xce, 0x92, 0x6a,
    0x0a, 0x09, 0xa5, 0x55, 0x8c, 0xb5, 0x80, 0x50, 0xca, 0xe0, 0xe2, 0x25, 0x86, 0x47, 0x63, 0xe4,
    0xd9, 0xce, 0xc2, 0x0d, 0xf0, 0x5a, 0x5b, 0xf0, 0x05, 0xb9, 0x77, 0xf3, 0xbb, 0x55, 0xed, 0xa5,
};

HI_U8 g_au8CustomerRSAPublicKey_E_100001[SSA_LEN_RSA_PUBLIC_KEY_E] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01
};

HI_U8 g_au8CustomerRSAPublicKey_E_10001[SSA_LEN_RSA_PUBLIC_KEY_E] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01
};

HI_U8 g_au8CustomerRSAPublicKey_E_3[SSA_LEN_RSA_PUBLIC_KEY_E] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
};

static HI_U32 s_s32CustomerRSAPublicKey_E = 0x00000003;

static HI_S32 ssaGetRSAVerifyParam(HI_UNF_CIPHER_RSA_VERIFY_S* pstVerifyParam)
{
    SSA_DBG_FuncEnter();

    switch (s_s32CustomerRSAPublicKey_E)
    {
        case 0x00000003:
        {
            pstVerifyParam->stPubKey.pu8E = g_au8CustomerRSAPublicKey_E_3;
            break;
        }
        case 0x00100001:
        {
            pstVerifyParam->stPubKey.pu8E = g_au8CustomerRSAPublicKey_E_100001;
            break;
        }
        case 0x0010001:
        {
            pstVerifyParam->stPubKey.pu8E = g_au8CustomerRSAPublicKey_E_10001;
            break;
        }
        default:
        {
            SSA_PrintErrCode(SSA_ERR_EXTERNAL);
            return SSA_ERR_EXTERNAL;
        }
    }

    pstVerifyParam->stPubKey.u16ELen = SSA_LEN_RSA_PUBLIC_KEY_E;
    pstVerifyParam->stPubKey.u16NLen = SSA_LEN_RSA_PUBLIC_KEY_N;
    pstVerifyParam->stPubKey.pu8N    = g_au8CustomerRSAPublicKey_N;
    pstVerifyParam->enScheme         = HI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA256;

    SSA_DBG_FuncExit();
    return HI_SUCCESS;
}

HI_S32 SSA_CIPHER_Init(HI_VOID)
{
    HI_S32 s32Ret = HI_FAILURE;

    SSA_DBG_FuncEnter();

    s32Ret = HI_UNF_CIPHER_Init();
    if (HI_SUCCESS != s32Ret )
    {
        SSA_PrintFuncErr(HI_UNF_CIPHER_Init, s32Ret);
        return SSA_ERR_EXTERNAL;
    }

    SSA_DBG_FuncExit();
    return HI_SUCCESS;
}

HI_S32 SSA_CIPHER_DeInit(HI_VOID)
{
    HI_S32 s32Ret = HI_FAILURE;

    SSA_DBG_FuncEnter();

    s32Ret = HI_UNF_CIPHER_DeInit();
    if (HI_SUCCESS != s32Ret )
    {
        SSA_PrintFuncErr(HI_UNF_CIPHER_DeInit, s32Ret);
        return SSA_ERR_EXTERNAL;
    }

    SSA_DBG_FuncExit();
    return HI_SUCCESS;
}

HI_S32 SSA_CIPHER_HashVerify(SSA_HASH_TYPE_E enHashType, HI_U8* pu8Data, HI_U32 u32Size, HI_U8* pu8Value)
{
    HI_U8 au8HashValue[SSA_LEN_HMAXVALUE] = {0};
    HI_UNF_CIPHER_HASH_ATTS_S stHashAttr;
    HI_HANDLE hHashHandle = HI_NULL_PTR;
    HI_S32 s32Ret = HI_FAILURE;

    SSA_DBG_FuncEnter();

    SSA_CHECK_PARAM(HI_NULL_PTR == pu8Data);
    SSA_CHECK_PARAM(HI_NULL_PTR == pu8Value);
    SSA_CHECK_PARAM(0 == u32Size);

    memset(&stHashAttr, 0x00, sizeof(stHashAttr));

    switch (enHashType)
    {
        case SSA_HASH_TYPE_1:
        {
            stHashAttr.eShaType = HI_UNF_CIPHER_HASH_TYPE_SHA1;
            break;
        }
        case SSA_HASH_TYPE_2:
        {
            stHashAttr.eShaType = HI_UNF_CIPHER_HASH_TYPE_SHA256;
            break;
        }
        default:
        {
            SSA_PrintErrCode(SSA_ERR_PARAM);
            return SSA_ERR_PARAM;
        }
    }

#ifdef HI_LOADER_BOOTLOADER
    stHashAttr.u32TotalDataLen = u32Size;
#endif

    s32Ret = HI_UNF_CIPHER_HashInit(&stHashAttr, &hHashHandle);
    if (HI_SUCCESS != s32Ret)
    {
        SSA_PrintFuncErr(HI_UNF_CIPHER_HashInit, s32Ret);
        return SSA_ERR_EXTERNAL;
    }

    s32Ret = HI_UNF_CIPHER_HashUpdate(hHashHandle, pu8Data, u32Size);
    if (HI_SUCCESS != s32Ret)
    {
        SSA_PrintFuncErr(HI_UNF_CIPHER_HashUpdate, s32Ret);
        return SSA_ERR_EXTERNAL;
    }

    s32Ret = HI_UNF_CIPHER_HashFinal(hHashHandle, au8HashValue);
    if (HI_SUCCESS != s32Ret)
    {
        SSA_PrintFuncErr(HI_UNF_CIPHER_HashFinal, s32Ret);
        return SSA_ERR_EXTERNAL;
    }

    SSA_PrintBuffer("ImageHashValue:", pu8Value, SSA_DCAS_LEN_SHA_VALUE);
    SSA_PrintBuffer("CalcuHashValue:", au8HashValue, SSA_DCAS_LEN_SHA_VALUE);

    if (0 != memcmp(au8HashValue, pu8Value, SSA_LEN_HMAXVALUE))
    {
        SSA_PrintErrCode(SSA_ERR_DATABASE);
        return SSA_ERR_DATABASE;
    }

    SSA_DBG_FuncExit();
    return HI_SUCCESS;
}

HI_S32 SSA_CIPHER_RSAVerify(HI_U8* pu8Data, HI_U32 u32Size, HI_U8* pu8Signature, HI_U32 u32SignatureSize)
{
    HI_UNF_CIPHER_RSA_VERIFY_S stRsaVerify;
    HI_S32 s32Ret = HI_FAILURE;

    SSA_DBG_FuncEnter();

    SSA_CHECK_PARAM(HI_NULL_PTR == pu8Data);
    SSA_CHECK_PARAM(HI_NULL_PTR == pu8Signature);

    SSA_CHECK_PARAM(0 == u32Size);
    SSA_CHECK_PARAM(0 == u32SignatureSize);

    memset(&stRsaVerify, 0x00, sizeof(stRsaVerify));

    s32Ret = ssaGetRSAVerifyParam(&stRsaVerify);
    if (HI_SUCCESS != s32Ret)
    {
        SSA_PrintFuncErr(ssaGetRSAVerifyParam, s32Ret);
        return SSA_ERR_EXTERNAL;
    }

    s32Ret = HI_UNF_CIPHER_RsaVerify(&stRsaVerify, pu8Data, u32Size, HI_NULL_PTR, pu8Signature, u32SignatureSize);
    if (HI_SUCCESS != s32Ret)
    {
        SSA_PrintFuncErr(HI_UNF_CIPHER_RsaVerify, s32Ret);
        return SSA_ERR_EXTERNAL;
    }

    SSA_DBG_FuncExit();
    return HI_SUCCESS;
}


HI_S32 SSA_CIPHER_SetRSAPublicKey(HI_U8* pu8RsaData, HI_U32 u32Length)
{
    SSA_DBG_FuncEnter();

    SSA_CHECK_PARAM(HI_NULL_PTR == pu8RsaData);
    SSA_CHECK_PARAM(SSA_DCAS_LEN_RSAPUBLICKEY > u32Length);

    memcpy(g_au8CustomerRSAPublicKey_N, pu8RsaData, SSA_LEN_RSA_PUBLIC_KEY_N);

    s_s32CustomerRSAPublicKey_E = (pu8RsaData[SSA_POS_RSA_PUBLIC_KEY_E] << 24)
                                + (pu8RsaData[SSA_POS_RSA_PUBLIC_KEY_E + 1] << 16)
                                + (pu8RsaData[SSA_POS_RSA_PUBLIC_KEY_E + 2] << 8)
                                + (pu8RsaData[SSA_POS_RSA_PUBLIC_KEY_E + 3]);
    SSA_DBG_FuncExit();
    return HI_SUCCESS;
}

HI_S32 SSA_CIPHER_GetRandomNum(HI_U32* pu32Random)
{
    HI_S32 s32Ret = HI_FAILURE;

    SSA_CHECK_PARAM(HI_NULL_PTR == pu32Random);

    SSA_DBG_FuncEnter();

    s32Ret = HI_UNF_CIPHER_GetRandomNumber(pu32Random);
    if (HI_SUCCESS != s32Ret)
    {
        SSA_PrintFuncErr(HI_UNF_CIPHER_GetRandomNumber, s32Ret);
        return s32Ret;
    }

    SSA_DBG_FuncExit();
    return HI_SUCCESS;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

